<?php

/**
 * 框架应用调度
 *
 * @author JiangJian <silverd@sohu.com>
 * $Id: App.php 171 2012-11-14 06:39:25Z silverd30@gmail.com $
 */

class Core_App
{
    /**
     * 路由分发信息
     *
     * @var array
     */
    private $_dispatchInfo = array();

    /**
     * 本请求是否已完成所有分发
     *
     * @var bool
     */
    private $_dispatched = true;

    /**
     * 是否命令行模式
     *
     * @var bool
     */
    private $_isCli = false;

    private static $_instance;
    public static function getInstance()
    {
        if (self::$_instance === null) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    public function __construct()
    {
        // 框架初始化
        require SYS_PATH . 'Core/Bootstrap.php';
        Core_Bootstrap::init();

        // 类自动加载机制
        spl_autoload_register(array($this, 'autoload'));

        // 初始化、注册插件
        Core_Plugin_Broker::init();
    }

    /**
     * 执行主流程
     *
     * @param $controllerPath
     * @return void
     */
    public function run($controllerPath = 'Controller')
    {
        try {

            // 插件调用：路由解析前
            Core_Plugin_Broker::invoke('routerStartup');

            // 路由解析，设置当前分发信息
            $this->setDispatchInfo(null);
            if (!$this->_dispatchInfo) {
                throw new Core_Exception_Fatal('No dispatchInfo found');
            }

            // 插件调用：路由解析后
            Core_Plugin_Broker::invoke('routerShutdown');

            // 插件调用：循环分发前
            Core_Plugin_Broker::invoke('dispatchLoopStartup');

            do {

                $this->_dispatched = true;

                // 插件调用：分发前
                Core_Plugin_Broker::invoke('preDispatch');

                // 执行分发
                Core_Dispatcher::getInstance()->dispatch($this->_dispatchInfo, $controllerPath);

                // 插件调用：分发后
                Core_Plugin_Broker::invoke('postDispatch');

            } while (!$this->_dispatched);

            // 插件调用：循环分发后
            Core_Plugin_Broker::invoke('dispatchLoopShutdown');

        } catch (Exception $e) {

            if ($this->_isCli) {
                exit($e);
            }

            // 错误、异常处理控制器
            $dispatchInfo = array(
                'controller' => 'Error',
                'action'     => 'error',
                'params'     => array(
                    'exception' => $e,
                ),
            );
            Core_Dispatcher::getInstance()->dispatch($dispatchInfo, $controllerPath);
        }
    }

    /**
     * 类自动加载机制
     *
     * @param string $className
     */
    public function autoload($className)
    {
        $classPath = $className;
        if (strpos($className, '_') !== false) {
            $classPath = str_replace('_', DIRECTORY_SEPARATOR, $className);
        }

        require_once $classPath . '.php';

        if (!class_exists($className, false) && !interface_exists($className, false)) {
            throw new Core_Exception_Fatal('Unable to load class: ' . $className);
        }
    }

    public function setDispatchInfo($dispatchInfo = null)
    {
        if (null === $dispatchInfo) {
            $pathInfo = $this->_isCli ? Core_Router::getCliPathInfo() : Core_Router::getPathInfo();
            $dispatchInfo = Core_Router::parse($pathInfo);
        }

        $this->_dispatchInfo = $dispatchInfo;
        return $this;
    }

    public function getDispatchInfo()
    {
        return $this->_dispatchInfo;
    }

    public function setCli($isCli = true)
    {
        $this->_isCli = $isCli;
        return $this;
    }

    public function setDispatched($dispatched = true)
    {
        $this->_dispatched = $dispatched;
        return $this;
    }
}